<script setup lang="ts">
import { computed, type VNode } from "vue";
import { CloseOutlined } from "@ant-design/icons-vue";

interface Props {
  open?: boolean;
  icon?: VNode;
  title?: string;
  destroyOnClose?: boolean;
  closable?: boolean;
  centered?: boolean;
  footer?: VNode | undefined | null;
  cancelText?: string;
  okText?: string;
  afterClose?: () => void;
  width?: string | number;
  /**
   * 点击确定执行的钩子,如果返回false则不会关闭窗口
   */
  beforeOk?: () => Promise<boolean> | boolean;
}

const { icon, open, title, destroyOnClose = true, closable = true, centered = true, beforeOk } = defineProps<Props>();

const emits = defineEmits<{
  (e: "update:open", open: boolean): void;
  (e: "cancel"): void;
  (e: "ok", args?: any): void;
}>();

const isOpen = computed({
  get: () => open,
  set: value => emits("update:open", value),
});

const handleCancel = () => {
  isOpen.value = false;
  emits("cancel");
};

const handleOk = async () => {
  if (beforeOk) {
    const next = await beforeOk();
    if (!next) return;
  }

  isOpen.value = false;
  emits("ok");
};
</script>

<template>
  <a-modal
    v-model:open="isOpen"
    class="dialog-window"
    :destroy-on-close="destroyOnClose"
    :closable="false"
    :centered="centered"
    :after-close="afterClose"
    :width="width"
  >
    <template #title>
      <div class="dialog-window-header">
        <slot name="icon">
          <component v-if="icon" :is="icon" />
        </slot>
        <div class="flex-1">
          <slot name="title">
            <span class="font-14 bold">{{ title }}</span>
          </slot>
        </div>

        <div class="dialog-window-button-container">
          <slot name="headerButtons"></slot>
          <button v-if="closable" class="dialog-window-button close-button" @click="isOpen = false">
            <CloseOutlined />
          </button>
        </div>
      </div>
    </template>
    <slot></slot>
    <template #footer>
      <component v-if="footer !== undefined" :is="footer" />
      <slot v-else name="footer">
        <a-space>
          <a-button @click="handleCancel">{{ cancelText || "取消" }}</a-button>
          <a-button @click="handleOk" type="primary">{{ okText || "确定" }}</a-button>
        </a-space>
      </slot>
    </template>
  </a-modal>
</template>

<style lang="less">
.dialog-window {
  .ant-modal-content {
    padding: 0 !important;
  }

  .ant-modal-header {
    margin-bottom: 0 !important;
  }

  @header-size: 32px;

  &-header {
    display: flex;
    align-items: center;
    height: @header-size;
    padding-left: 10px;
    column-gap: 10px;
  }

  &-button-container {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    height: @header-size;
  }

  &-button {
    width: @header-size;
    height: @header-size;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    outline: none;
    border: none;
    background: transparent;
    color: var(--color-text);
    transition: all 0.2s;

    &:hover {
      background-color: var(--color-bg-text-hover);
    }

    &.close-button {
      &:hover {
        color: var(--color-error);
      }
    }
  }

  .ant-modal-footer {
    padding-bottom: 10px;
    padding-left: 10px;
    padding-right: 10px;
    margin-top: 0 !important;
  }
}
</style>
